package com.cy.letcode.缓存失效策略.LRU;

import java.util.HashMap;
import java.util.Map;

/**
 * //2、 设计一个LRU Cache，即根据LRU算法设计一个缓存，它支持两个操作：
 * //1）get(key)：如果key在cache中，则返回对应的value值，否则返回-1
 * //2）set(key,value):如果key不在cache中，则将该(key,value)插入cache中（注意，如果cache已满，则必须把最近最久未使用的元素从cache中删除）；
 * 如果key在cache中，则重置value的值
 *
 * @author chen_yu
 */
public class LRUCache {

    public static void main(String[] args) {
        LRUCache lRUCache = new LRUCache(2);
        lRUCache.put(2, 1); // 缓存是 {1=1}
        lRUCache.put(1, 1); // 缓存是 {1=1, 2=2}
        lRUCache.put(2, 3); // 该操作会使得关键字 2 作废，缓存是 {1=1, 3=3}
        lRUCache.put(4, 1); // 该操作会使得关键字 1 作废，缓存是 {4=4, 3=3}
        lRUCache.get(1);    // 返回 -1 (未找到)
        lRUCache.get(2);    // 返回 3

    }

    /**
     * 定义一个双向链表
     */
    class DeLinkNode {
        Integer key;
        Integer value;
        DeLinkNode pre;
        DeLinkNode next;

        public DeLinkNode() {
        }

        public DeLinkNode(Integer key, Integer value) {
            this.key = key;
            this.value = value;
        }


    }

    private static Map<Integer, DeLinkNode> map = new HashMap<>();
    /**
     * 定义当前缓存大小
     */
    private int size;
    /**
     * 定义缓存容量
     */
    private final int capacity;

    /**
     * 定义虚拟头部节点和尾部节点
     */
    private DeLinkNode head, tail;


    public LRUCache(int capacity) {
        head = new DeLinkNode();
        tail = new DeLinkNode();
        head.next = tail;
        tail.pre = head;
        this.capacity = capacity;
    }

    public int get(int key) {
        DeLinkNode node = map.get(key);
        if (node == null) {
            System.out.println(-1);
            return -1;
        }
        moveToHead(node);
        System.out.println(node.value);
        return node.value;
    }

    public void put(int key, int value) {
        //先判断缓存中是否有此节点
        DeLinkNode node = map.get(key);
        if (node != null) {
            //否则就说明存在节点
            node.value = value;
            moveToHead(node);
            return;
        }
        if (size >= capacity) {
            //如果当前容量超过了就要进行删除移除操作
            DeLinkNode deLinkNode = removeFromTail();
            map.remove(deLinkNode.key);
            size--;
        }
        //如果为空说明当前没有缓存 添加至头部
        node = new DeLinkNode(key, value);
        //加到头部
        addToHead(node);
        map.put(key, node);
        size++;

    }

    /**
     * head->1->2->3->tail
     * head<-1<-2<-3<-tail
     */
    private void moveToHead(DeLinkNode node) {
        removeNode(node);
        addToHead(node);
    }

    private DeLinkNode removeFromTail() {
        DeLinkNode node = tail.pre;
        removeNode(node);
        return node;
    }

    private void removeNode(DeLinkNode node) {
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    private void addToHead(DeLinkNode node) {
        node.next = head.next;
        node.pre = head;
        head.next.pre = node;
        head.next = node;
    }


}
